// clause.go
package main

import (
	"fmt"
	"strconv"
	//	"strings"
	// "strings"
)

const (
// ClauseType_CONSTANT = -2 //指常量
// ClauseType_VAR      = -1 //指单值变量
// ClauseType_SINGLE   = 0  //指最普通的单条语句
// ClauseType_FOR      = 1  //FOR语句
// ClauseType_IF       = 2  //IF语句

)

type DrClause struct {
	DrAbstractObject
	//object     *DrClause //函数所属对象，用Clause替代，对象在Clause求解后确定
	funcName   string //函数名
	funcIndex  int    //函数在object函数列表中的索引，加速优化时用
	ClauseType ClauseTypeIndex
	//funcName   string
	parameters []*DrClause //用于存放函数调用的实参，或者是if语句的条件语句，以及for迭代所用的语句。if和for默认使用第0个位置上的子句
	//result     *Object  //暂时应该不用该成员
	returnName string
	subClauseA []*DrClause //用于存放if后面或for分路下面的子句
	subClauseB []*DrClause //用于存放else后面的子句
	//ElseIndex  int         //用于存放else子句的起始分界
	Value    interface{}
	__locals []IObject
	__object IObject
}

//创建for子句
func NewClauseFOR() *DrClause {
	clause := new(DrClause)
	clause.ClauseType = ClauseType_FOR
	return clause
}

//创建while子句
func NewClauseWHILE() *DrClause {
	clause := new(DrClause)
	clause.ClauseType = ClauseType_WHILE
	return clause
}

//创建if子句
func NewClauseIF() *DrClause {
	clause := new(DrClause)
	clause.ClauseType = ClauseType_IF
	return clause
}

// func (self *DrClause) getMembers() map[string]*DrObject {
// 	return self.object.class.members
// }
func (self *DrClause) Print() {
	//对非复合型的常规语句
	if self.ClauseType != ClauseType_FOR && self.ClauseType != ClauseType_IF {
		if self.funcName[0] == '.' {
			self.parameters[0].Print()
		}
		fmt.Print(self.funcName)
		if self.ClauseType == ClauseType_SINGLE {
			fmt.Print("(")
		}
		for i, v := range self.parameters {
			if self.funcName[0] == '.' && i == 0 { //当函数名中有点时，第一个参数不再打印
				continue
			}
			if v == nil {
				fmt.Println("None")
				continue
			}
			if v.ClauseType == ClauseType_SINGLE {
				v.Print()
				fmt.Print(",")
			} else if v.ClauseType == ClauseType_VAR {
				fmt.Print(v.funcName, ",")
			} else if v.ClauseType == ClauseType_CONSTANT {
				if v.Type == TypeString {
					fmt.Print(v.funcName, ",")
				} else if v.Type == TypeNum {
					fmt.Print(v.getValue(), ",")
				} else if v.Type == TypeInt {
					fmt.Println(v.Value)
				} else {
					panic("not implemented" + string(v.Type))
				}

			} else {
				panic("not implemented" + string(v.ClauseType))
			}

		}

		if self.ClauseType == ClauseType_SINGLE {
			fmt.Print(")")
		}
	}
	//for子句
	if self.ClauseType == ClauseType_FOR {
		fmt.Print("\nFor ")
		self.parameters[0].Print()
		fmt.Println("\nFor Body:")
		for _, cl := range self.subClauseA {
			cl.Print()
		}
		fmt.Println("\nend for")
	}
	//if子句
	if self.ClauseType == ClauseType_IF {
		fmt.Print("\nIf ")
		self.parameters[0].Print()
		fmt.Println("\nIf Body:")
		for _, cl := range self.subClauseA {
			cl.Print()
		}
		fmt.Println("\nElse Body:")
		for _, cl := range self.subClauseB {
			cl.Print()
		}
		fmt.Println("\nend if")
	}
	//	fmt.Println()
}

func (self *DrClause) AddParam(para *DrClause) {
	if self.ClauseType == ClauseType_VAR {
		panic("Varible type object cannot be used as a varible")
	}
	self.parameters = append(self.parameters, para)
}

// func (self *Clause) AddReturnValue(m_var string) {
// 	if self.ClauseType == ClauseType_VAR {
// 		panic("Varible type object cannot be used as a varible")
// 	}
// 	self.returnVarNames = append(self.returnVarNames, m_var)
// }
func (self *DrClause) AddParameter(parm *DrClause) {
	//if self.ClauseType == ClauseType_VAR {
	//	panic("Variable type object cannot be used as a varible")
	//}
	self.parameters = append(self.parameters, parm)
}
func (self *DrClause) getVariable() string {
	//if self.ptype == Type_Clause {
	//	panic("Clause type object cannot be used as a varible")
	//}
	//if self.ptype == Type_Variable {
	//	n := len(self.returnVarNames)
	return self.funcName
	//}

}
func (self *DrClause) setVariable(value string) {
	if self.ClauseType == ClauseType_SINGLE {
		panic("Clause type object cannot be used as a varible:")
	}
	self.ClauseType = ClauseType_VAR
	self.funcName = value
}
func (self *DrClause) setConstant(value string) {
	v, err := strconv.ParseFloat(value, 64)
	if err == nil {
		self.ClauseType = ClauseType_CONSTANT
		self.Value = v
		self.funcName = value
	}
}
func (self *DrClause) getValue() float64 {
	v, _ := strconv.ParseFloat(self.funcName, 64)
	return v
}
func (self *DrClause) GetChildSize() int {
	return len(self.subClauseA)
}
func (self *DrFunction) AddClause3(clause *DrClause) {
	self.Clauses = append(self.Clauses, clause)
}
func (self *DrFunction) ClauseCount() int {
	return len(self.Clauses)
}
func (self *DrFunction) AddClause2(funcName string, paraNames []*DrClause, returnVar string) {
	clause := new(DrClause)
	clause.funcName = funcName
	clause.parameters = paraNames
	clause.returnName = returnVar
	self.Clauses = append(self.Clauses, clause)
}
func (self *DrFunction) AsString() string {
	return "<function " + self.Name + ">"
}
func (self *DrFunction) Print(interp *Interpreter) {
	fmt.Print(self.AsString() + " ")
}
func (self *DrFunction) AddClause(funcName string, paraNames []string, returnVar string) {
	clause := new(DrClause)
	clause.ClauseType = ClauseType_SINGLE
	clause.funcName = funcName
	clause.parameters = make([]*DrClause, 0, 10)
	for i := 0; i < len(paraNames); i++ {
		cl := new(DrClause)
		cl.ClauseType = ClauseType_SINGLE
		value, err := strconv.ParseFloat(paraNames[i], 64)
		if err == nil {
			cl.ClauseType = ClauseType_CONSTANT
			cl.Value = value
		} else {

			cl.ClauseType = ClauseType_VAR
			cl.funcName = paraNames[i]
		}
		cl.funcName = paraNames[i]
		clause.parameters = append(clause.parameters, cl)
	}
	clause.returnName = returnVar
	self.Clauses = append(self.Clauses, clause)
}
